package com.atguigu.lease.web.app.service.impl;


import com.atguigu.lease.common.constant.RedisConstant;
import com.atguigu.lease.common.exception.LeaseException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.common.utils.JwtUtil;
import com.atguigu.lease.common.utils.VerifyCodeUtil;
import com.atguigu.lease.model.entity.UserInfo;
import com.atguigu.lease.model.enums.BaseStatus;
import com.atguigu.lease.web.app.service.LoginService;
import com.atguigu.lease.web.app.service.SmsService;
import com.atguigu.lease.web.app.service.UserInfoService;
import com.atguigu.lease.web.app.vo.user.LoginVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private RedisTemplate<String,String> redisTemplate ;

    @Autowired
    private SmsService smsService ;

    @Autowired
    private UserInfoService userInfoService;

    @Override
    public void getSMSCode(String phone) throws Exception {
        //1.判断手机号码是否为空
        if(!StringUtils.hasLength(phone)){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_PHONE_EMPTY);
        }
        //2.发消息
        //生成key
        String key = RedisConstant.APP_LOGIN_PREFIX+phone;
        //生成验证码
        String code = VerifyCodeUtil.getVerifyCode(6);
        //2-1. 判断是否频繁发送短消息
        /*
        // getExpire  -> 剩余有效时长4分30秒
        // APP_LOGIN_CODE_TTL_SEC -> 总有效时长 5分钟
        // 5分钟 - 4分30秒 < 1分钟
        如果一分钟内刚刚给这个手机号发送过验证码的，则判定为发送频繁
         */
        Long expire = redisTemplate.getExpire(key, TimeUnit.SECONDS); //key对应的验证码剩余的有效时长
        if((RedisConstant.APP_LOGIN_CODE_TTL_SEC - expire ) < RedisConstant.APP_LOGIN_CODE_RESEND_TIME_SEC){
            throw new LeaseException(ResultCodeEnum.APP_SEND_SMS_TOO_OFTEN);
        }
        //2-2. 发消息
        smsService.sendCode(phone,code);
        //3.将手机号和验证码存储到redis中
        redisTemplate.opsForValue().set(key,code,RedisConstant.APP_LOGIN_CODE_TTL_SEC, TimeUnit.SECONDS);
    }

    @Override
    public String login(LoginVo loginVo) {

        //1.判断手机号是否为空
        if(!StringUtils.hasLength(loginVo.getPhone())){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_PHONE_EMPTY);
        }
        //2.判断短信验证码是否为空
        if(!StringUtils.hasLength(loginVo.getCode())){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_CODE_EMPTY);
        }

        //3.判断redis中验证码是否为空
        String key = RedisConstant.APP_LOGIN_PREFIX+loginVo.getPhone();
        String codeFromRedis = redisTemplate.opsForValue().get(key);
        Boolean flag = redisTemplate.hasKey(key);
        if(!flag){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_CODE_EXPIRED);
        }

        //4.判断验证码是否相等
        if(!loginVo.getCode().equals(codeFromRedis)){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_CODE_ERROR);
        }

        //5.从数据库查询用户, 如果数据库中发现没有这个手机号的用户，说明是新用户，自动注册
        UserInfo userInfoFromDB = userInfoService.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getPhone, loginVo.getPhone()));
        if(userInfoFromDB==null){
            userInfoService.save(userInfoFromDB);
        }

        //6.判断用户的状态是否是禁用状态
        if(userInfoFromDB.getStatus()== BaseStatus.DISABLE){
            throw new LeaseException(ResultCodeEnum.APP_ACCOUNT_DISABLED_ERROR);
        }

        //7.生成token
        return JwtUtil.createToken(userInfoFromDB.getId(),userInfoFromDB.getPhone());
    }
}
